import {
  CanActivate,
  ExecutionContext,
  Inject,
  Injectable,
  UnauthorizedException,
} from "@nestjs/common";
import { JwtService } from "@nestjs/jwt";
import { Request } from "express";
import { Reflector } from "@nestjs/core";

import { configuration, NeedAuthPath } from "../../../config/config";
import { Constants } from "../../../types/types";
import { jwtConstants } from "@app/auth/constants";
import { UserService } from "@app/user";
import { LogService } from "@app/log";

@Injectable()
export class AuthGuard implements CanActivate {
  @Inject()
  private reflector: Reflector;

  constructor(
    private jwtService: JwtService,
    private userService: UserService,
    private logService: LogService,
  ) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const request = context.switchToHttp().getRequest();
    console.log(request.url, 111111);
    if (!configuration.open_auth) {
      return true;
    }

    if (this.checkHasNoNeedAuthDecorator(context)) {
      return true;
    }
    const path = request.url;

    // 如果该接口不需要鉴权，那么直接跳过。
    if (!NeedAuthPath.includes(path)) {
      return true;
    }
    return  await this.checkTokenAndAuth(request)
  }

  private extractTokenFromHeader(request: Request): string | undefined {
    const [type, token] = request.headers.authorization?.split(" ") ?? [];
    return type === "Bearer" ? token : undefined;
  }

  private checkHasNoNeedAuthDecorator(context) {
    const NoNeedLogin = this.reflector.getAllAndOverride(
      Constants.MetaKey.noNeedLogin,
      [context.getClass(), context.getHandler()],
    );

    if (NoNeedLogin) {
      return true;
    }
  }

  private async checkTokenAndAuth(request) {
    const token = this.extractTokenFromHeader(request);
    const path = request.url;
    if (!token) {
      return false;
    }
    try {
      const user = await this.jwtService.verifyAsync(token, {
        secret: jwtConstants.secret,
      });
      const currentUserPermissions =
        await this.userService.getPermissionByUserId(user.userId);
      this.logService.log(
        "登录成功，用户信息为：",
        `该用户的权限为：${JSON.stringify(currentUserPermissions)}`,
      );

      const permissionPaths = currentUserPermissions.map(
        (permission) => permission.path,
      );
      if (permissionPaths.includes(path)) {
        console.log("鉴权成功");
        request.user = user;
        return true;
      } else {
        return false;
      }
    } catch {
      return false;
    }
  }
}
